package cn.org.timespace.easyframe.util.jasper;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRMapCollectionDataSource;
import net.sf.jasperreports.engine.export.JRCsvExporter;
import net.sf.jasperreports.engine.export.JRHtmlExporter;
import net.sf.jasperreports.engine.export.JRHtmlExporterParameter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRRtfExporter;
import net.sf.jasperreports.engine.export.JRTextExporter;
import net.sf.jasperreports.engine.export.JRTextExporterParameter;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import net.sf.jasperreports.engine.export.JRXlsExporterParameter;
import net.sf.jasperreports.engine.export.JRXmlExporter;

/**
 * <p>
 * 报表展现和导出的工具类
 * </p>
 * 
 * @version 1.0, 11/01/18
 * @since 1.0
 * @author 
 */

public class EfJasperReportUtil {

	public final static int PDF_FILE = 1; // PDF类型

	public final static int EXCEL_FILE = 2; // EXCEL类型

	public final static int XML_FILE = 3; // XML类型

	public final static int HTML_FILE = 4; // HTML类型

	public final static int RTF_FILE = 5; // RTF类型

	public final static int CSV_FILE = 6; // CSV类型

	public final static int TEXT_FILE = 7; // TEXT类型

	/**
	 * 根据.jasper文件、参数、数据源生成JasperPrint
	 * 
	 * @param jasperFile
	 *            .jasper文件
	 * @param jasperParameters
	 *            报表参数
	 * @param datasource
	 *            JRMapCollectionDataSource类型的数据源
	 * @return
	 * @throws Exception
	 */
	public static JasperPrint getJasperPrint(File jasperFile,
			Map jasperParameters, JRMapCollectionDataSource datasource)
			throws Exception {
		// check .jasper exist
		if (!jasperFile.exists()) {
			throw new JRRuntimeException(jasperFile.getName()
					+ " not found.!!! ");
		}
		// check jasper parameter
		if (jasperParameters == null) {
			jasperParameters = new HashMap();
		}
		// produce jasperPrint
		JasperPrint jasperPrint = JasperFillManager.fillReport(jasperFile
				.getPath(), jasperParameters, datasource);

		return jasperPrint;
	}

	/**
	 * 根据.jasper文件、参数、数据连接生成JasperPrint
	 * 
	 * @param jasperFile
	 *            .jasper文件
	 * @param jasperParameters
	 *            报表参数
	 * @param connection
	 *            数据连接
	 * @return
	 * @throws Exception
	 */
	public static JasperPrint getJasperPrint(File jasperFile,
			Map jasperParameters, Connection connection) throws Exception {
		
		// check .jasper exist
		if (!jasperFile.exists()) {
			throw new JRRuntimeException(jasperFile.getName()
					+ " not found.!!! ");
		}
		// check jasper parameter
		if (jasperParameters == null) {
			jasperParameters = new HashMap();
		}
		JasperPrint jasperPrint = null;
		try {
			// produce jasperPrint
			jasperPrint = JasperFillManager.fillReport(jasperFile.getPath(),
					jasperParameters, connection);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			connection.close(); // 关闭连接
		}
		return jasperPrint;
	}

	/**
	 * 获取exporter
	 * 
	 * @param jasperPrint
	 * @param fileType
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public static JRExporter getExporter(JasperPrint jasperPrint, int fileType)
			throws Exception {
		JRExporter exporter = null;
		// 根据文件类型获取相应的JRExporter实例
		switch (fileType) {
		case PDF_FILE:
			exporter = new JRPdfExporter();
			break;
		case EXCEL_FILE:
			exporter = new JRXlsExporter();
			break;
		case XML_FILE:
			exporter = new JRXmlExporter();
			break;
		case HTML_FILE:
			exporter = new JRHtmlExporter();
			break;
		case RTF_FILE:
			exporter = new JRRtfExporter();
			break;
		case CSV_FILE:
			exporter = new JRCsvExporter();
			break;
		case TEXT_FILE:
			exporter = new JRTextExporter();
			break;
		}
		// 设置exporter的JasperPrint
		exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
		// 设置exporter的character encoding
		exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "GB2312");

		// 如果是html的exporter还需设置它的图片属性
		if (fileType == HTML_FILE) {
			exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI,
					"./servlets/image?image=");
			/*
			 * exporter .setParameter(
			 * JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN, Boolean.FALSE);
			 */
		}

		// 如果是excel的expoerter设置margin和背景颜色
		if (fileType == EXCEL_FILE) {
			exporter
					.setParameter(
							JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_COLUMNS,
							Boolean.TRUE);
			exporter.setParameter(
					JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS,
					Boolean.TRUE);
			exporter.setParameter(
					JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND,
					Boolean.FALSE);
			exporter.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET,
					Boolean.FALSE);
		}

		// 如果是text的expoerter另需设置字符的width、height
		if (fileType == TEXT_FILE) {
			exporter.setParameter(JRTextExporterParameter.CHARACTER_WIDTH,
					new Integer(10));
			exporter.setParameter(JRTextExporterParameter.CHARACTER_HEIGHT,
					new Integer(10));
		}
		return exporter;
	}

	/**
	 * 获取报表内容的字节数组
	 * 
	 * @param exporter
	 * @return
	 * @throws Exception
	 */
	public static byte[] getReportBytes(JRExporter exporter) throws Exception {
		ByteArrayOutputStream bytesOutStream = new ByteArrayOutputStream();
		exporter
				.setParameter(JRExporterParameter.OUTPUT_STREAM, bytesOutStream);
		exporter.exportReport();

		return bytesOutStream.toByteArray();
	}

	/**
	 * 将报表内容导出时response的设置
	 * 
	 * @param response
	 * @param reportFileName
	 * @param fileType
	 *            1:PDF 2:EXCEL 3:XML 4:HTML 5:RTF 6:CSV 7:TEXT
	 * @param contentBytes
	 * @throws Exception
	 */
	public static void writeExportResponse(HttpServletResponse response,
			String reportFileName, int fileType, byte[] contentBytes)
			throws Exception {
		response.reset();
		
		// 根据文件类型生成相应的response的contentType
		String contentType = getContentType(fileType);
		
		response.setContentType(contentType);
		// 设置response附件名即导出报表的文件名,注意文件名乱码的处理
		response.setHeader("Content-disposition", "attachment;  filename="
				+ new String((reportFileName + "." + getFileSuffix(fileType))
						.getBytes("gb2312"), "ISO8859-1"));

		// 将报表内容的字节流写入response
		response.setContentLength(contentBytes.length);
		ServletOutputStream outputStream = response.getOutputStream();
		outputStream.write(contentBytes, 0, contentBytes.length);
		outputStream.flush();
		outputStream.close();
	}

	/**
	 * 提供将报表内容直接以html展示时response的设置
	 * 
	 * @param response
	 * @param contentBytes
	 * @throws Exception
	 */
	public static void writeDirectResponse(HttpServletResponse response,
			byte[] contentBytes,int fileType) throws Exception {
		response.reset();

		response.setContentType(getContentType(fileType)+";charset=gb2312");
		// 将报表内容的字节流写入response
		response.setContentLength(contentBytes.length);

		ServletOutputStream outputStream = response.getOutputStream();
		outputStream.write(contentBytes, 0, contentBytes.length);
		outputStream.flush();
		outputStream.close();

	}

	/**
	 * 当无须进行对JRExporter的格式进行设置时可使用该方法生成报表并以html直接在客户端进行展示
	 * 
	 * @param jasperFile
	 *            .jasper文件
	 * @param jasperParameters
	 *            报表参数
	 * @param dataSource
	 *            JRMapCollectionDataSource类型的数据源
	 * @param response
	 * @throws Exception
	 */
	public static void defaultDirectHtmlReport(File jasperFile,
			Map jasperParameters, JRMapCollectionDataSource dataSource,
			HttpServletResponse response) throws Exception {
		// get jasperprint
		JasperPrint jasperPrint = getJasperPrint(jasperFile, jasperParameters,
				dataSource);
		// get exporter
		JRExporter exporter = getExporter(jasperPrint, HTML_FILE);
		byte[] bytes = getReportBytes(exporter);
		writeDirectResponse(response, bytes,HTML_FILE);
	}

	/**
	 * 当无须进行对JRExporter的格式进行设置时可使用该方法生成报表并以html直接在客户端进行展示
	 * 
	 * @param jasperFile
	 *            .jasper文件
	 * @param jasperParameters
	 *            报表参数
	 * @param connection
	 *            数据连接
	 * @param response
	 * @throws Exception
	 */
	public static void defaultDirectReport(File jasperFile,
			Map jasperParameters, Connection connection,
			HttpServletResponse response,int fileType) throws Exception {
		// get jasperprint
		JasperPrint jasperPrint = getJasperPrint(jasperFile, jasperParameters,
				connection);
		// get exporter
		JRExporter exporter = getExporter(jasperPrint, fileType);
		byte[] bytes = getReportBytes(exporter);
		writeDirectResponse(response, bytes,fileType);
	}

	/**
	 * 当无须进行对JRExporter的格式进行设置时可使用该方法生成报表并以给定的文件格式导出
	 * 
	 * @param jasperFile
	 * @param jasperParameters
	 * @param dataSource
	 *            JRMapCollectionDataSource类型的数据源
	 * @param fileType
	 *            1:PDF 2:EXCEL 3:XML 4:HTML 5:RTF 6:CSV 7:TEXT
	 * @param reportFileName
	 * @param response
	 * @throws Exception
	 */
	public static void defaultExportReport(File jasperFile,
			Map jasperParameters, JRMapCollectionDataSource dataSource,
			int fileType, String reportFileName, HttpServletResponse response)
			throws Exception {
		JasperPrint jasperPrint = getJasperPrint(jasperFile, jasperParameters,
				dataSource);
		JRExporter exporter = getExporter(jasperPrint, fileType);
		byte[] bytes = getReportBytes(exporter);
		writeExportResponse(response, reportFileName, fileType, bytes);
	}

	/**
	 * 当无须进行对JRExporter的格式进行设置时可使用该方法生成报表并以给定的文件格式导出
	 * 
	 * @param jasperFile
	 * @param jasperParameters
	 * @param connection
	 *            数据连接
	 * @param fileType
	 *            1:PDF 2:EXCEL 3:XML 4:HTML 5:RTF 6:CSV 7:TEXT
	 * @param reportFileName
	 * @param response
	 * @throws Exception
	 */
	public static void defaultExportReport(File jasperFile,
			Map jasperParameters, Connection connection, int fileType,
			String reportFileName, HttpServletResponse response)
			throws Exception {
		JasperPrint jasperPrint = getJasperPrint(jasperFile, jasperParameters,
				connection);
		JRExporter exporter = getExporter(jasperPrint, fileType);
		byte[] bytes = getReportBytes(exporter);
		writeExportResponse(response, reportFileName, fileType, bytes);
	}

	/**
	 * 根据文件类型返回文件的后缀
	 * 
	 * @param fileType
	 *            1:PDF 2:EXCEL 3:XML 4:HTML 5:RTF 6:CSV 7:TEXT
	 * @return
	 */
	private static String getFileSuffix(int fileType) {
		String suffix = null;
		switch (fileType) {
		case PDF_FILE:
			suffix = "pdf";
			break;
		case EXCEL_FILE:
			suffix = "xls";
			break;
		case XML_FILE:
			suffix = "xml";
			break;
		case HTML_FILE:
			suffix = "html";
			break;
		case RTF_FILE:
			suffix = "rtf";
			break;
		case CSV_FILE:
			suffix = "csv";
			break;
		case TEXT_FILE:
			suffix = "txt";
			break;
		}
		return suffix;
	}
	
	private static String getContentType(final int fileType){
		String contentType = null;
		// 根据文件类型生成相应的response的contentType
		switch (fileType) {
		case PDF_FILE:
			contentType = "application/pdf";
			break;
		case EXCEL_FILE:
			contentType = "application/vnd.ms-excel";
			break;
		case XML_FILE:
			contentType = "text/xml";
			break;
		case HTML_FILE:
			contentType = "text/html";
			break;
		case RTF_FILE:
			contentType = "application/rtf";
			break;
		case CSV_FILE:
			contentType = "application/csv";
			break;
		case TEXT_FILE:
			contentType = "text/plain";
			break;
		}
		return contentType;
	}
}
